from typing import Callable

from pygame import Rect

from Lib.Core.UIBase import UIBase
from Lib.Utils import Console


def Image(resource_name, size):
    import pygame
    return pygame.transform.scale(Resource(resource_name), size)


def CutScreenBlack(_type="in", speed=8, _callable: [Callable] = None):
    from Lib.Core.UIResponse import UIResponse
    from constants import config
    from Lib.Core.Game import UILayer
    from constants import game
    window_size = eval(config.get("base", "window_size"))
    rect = [0, 0, window_size[0], window_size[1]]
    response = UIResponse(rect, UILayer.TOP.value)
    from Lib.Core.UISprite import UISprite
    if _type == "in":
        surface = GeneratorColorSurface(window_size, [0, 0, 0, 255])
    else:
        surface = GeneratorColorSurface(window_size, [0, 0, 0, 0])
    sprite = UISprite(surface)

    def Update(dt):
        alpha = surface.get_alpha()
        if _type == "in":
            alpha -= speed
        else:
            alpha += speed
        surface.set_alpha(alpha)
        if _type == "in":
            if alpha <= 0:
                response.Destroy()
                if _callable: _callable()
        else:
            if alpha >= 255:
                response.Destroy()
                if _callable: _callable()

    response.action_update = Update
    response.add(sprite)
    response.InitAction()
    game.ui_group.add(response)


def GeneratorColorSurface(size, color=None):
    if color is None:
        color = [0, 0, 0, 0]
    import pygame
    surface = pygame.surface.Surface(size).convert_alpha()
    surface.fill(color)
    if len(color) == 4:
        surface.set_alpha(color[3])
    return surface


def SetScene(scene_name):
    from constants import game
    from Scenes.LoadingScene import LoadingScene

    def Jump():
        game.scene = LoadingScene()
        game.scene.Load(scene_name)

    if game.scene:
        game.scene.Destroy()

        CutScreenBlack("out", _callable=Jump)
    else:
        Jump()


def Resource(resource_name):
    import locals
    return locals.resource.Get(resource_name)


def LoadResource(path):
    import os
    from constants import config
    file_info = os.path.splitext(path)
    file_type = file_info[1][1:]
    if str(path).startswith("https://") or str(path).startswith("http://"):
        from urllib import request
        import uuid
        _path = f"downloads/{uuid.uuid4().hex}.{file_type}"
        filename = config.get('base', 'resource_path') + _path
        for root, dirs, files in os.walk(config.get('base', 'resource_path') + "downloads/"):
            for name in files:
                del_file = os.path.join(root, name)
                os.remove(del_file)
        Console(f"正在下载资源: {path}", "info")
        request.urlretrieve(path, filename=filename)
        file_info = os.path.splitext(path)
        file_type = file_info[1][1:]
        path = _path
    if file_type == "png" or file_type == "jpg":
        import pygame
        path = config.get('base', 'resource_path') + path
        if os.path.exists(path):
            # Console(f"加载资源: {path}", "log", color=34)
            return pygame.image.load(path).convert_alpha()
        else:
            Console(f"找不到资源: {path}", "error")


def InUI(ui_layer, ui_base: UIBase):
    import locals
    return ui_base in locals.list_ui_collide[ui_layer]


def InAllUI(ui_base: UIBase):
    import locals
    return ui_base in locals.list_ui_collide['bot'] \
           + locals.list_ui_collide['mid'] \
           + locals.list_ui_collide['top'] \
           + locals.list_ui_collide['sys']


def TopUI():
    from Lib.Core.Game import UILayer
    import locals
    if locals.list_ui_collide[UILayer.SYS.value]:
        return locals.list_ui_collide[UILayer.SYS.value]
    if locals.list_ui_collide[UILayer.TOP.value]:
        return locals.list_ui_collide[UILayer.TOP.value]
    if locals.list_ui_collide[UILayer.MID.value]:
        return locals.list_ui_collide[UILayer.MID.value]
    if locals.list_ui_collide[UILayer.BOT.value]:
        return locals.list_ui_collide[UILayer.BOT.value]
    return []


def RemoveUI(ui_layer, ui_base: UIBase):
    from locals import list_ui_collide
    if ui_base in list_ui_collide[ui_layer]: list_ui_collide[ui_layer].remove(ui_base)


def RemoveUIInAll(ui_base: UIBase):
    from Lib.Core.Game import UILayer
    if InUI(UILayer.TOP.value, ui_base):
        RemoveUI(UILayer.TOP.value, ui_base)
    elif InUI(UILayer.MID.value, ui_base):
        RemoveUI(UILayer.MID.value, ui_base)
    elif InUI(UILayer.BOT.value, ui_base):
        RemoveUI(UILayer.BOT.value, ui_base)
    else:
        RemoveUI(UILayer.SYS.value, ui_base)


def CheckClick(ui_base: UIBase, rect: Rect, mouse_pos):
    if ui_base in TopUI() and rect.collidepoint(mouse_pos[0], mouse_pos[1]):
        return ui_base


def Text(text, color=None, font_size=None):
    if color is None:
        color = [255, 0, 0]
    import pygame
    from constants import config
    font_size = int(config.get('base', 'font_size_normal')) if not font_size else font_size
    font = pygame.font.Font(config.get('base', 'font_path'), font_size)
    return font.render(text, False, color, None)


def GeneratorAlphaSurface(size):
    from constants import config
    import pygame
    path = config.get("base", "resource_path") + "images/a.png"
    surface = pygame.image.load(path)
    return pygame.transform.scale(surface, size)


def ClearUI():
    import locals
    from constants import game
    from Lib.Core.UISprite import UISprite
    for sp in game.ui_group.sprites():
        if isinstance(sp, UIBase):
            sp.Destroy()
            if locals.mouse_click_focus_ui == sp:
                locals.mouse_click_focus_ui = None
            if locals.mouse_move_focus_ui == sp:
                locals.mouse_move_focus_ui = None
        elif isinstance(sp, UISprite):
            sp.Destroy()
            if locals.mouse_click_focus_sprite == sp:
                locals.mouse_click_focus_sprite = None
            if locals.mouse_move_focus_sprite == sp:
                locals.mouse_move_focus_sprite = None
        else:
            game.ui_group.remove(sp)
        locals.list_ui = {"bot": [], "mid": [], "top": []}


def ClearLayerUI(layer):
    from constants import game
    import locals
    from Lib.Core.UISprite import UISprite
    for sp in locals.list_ui[layer]:
        if isinstance(sp, UIBase):
            sp.Destroy()
            if locals.mouse_click_focus_ui == sp:
                locals.mouse_click_focus_ui = None
            if locals.mouse_move_focus_ui == sp:
                locals.mouse_move_focus_ui = None
        elif isinstance(sp, UISprite):
            sp.Destroy()
            if locals.mouse_click_focus_sprite == sp:
                locals.mouse_click_focus_sprite = None
            if locals.mouse_move_focus_sprite == sp:
                locals.mouse_move_focus_sprite = None
        else:
            game.ui_group.remove(sp)
        if sp in locals.list_ui[layer]: locals.list_ui[layer].remove(sp)


def Center(size):
    from constants import config
    _s = list(eval(config.get("base", "window_size")))
    pos = [int((_s[0] - size[0]) / 2), int((_s[1] - size[1]) / 2)]
    return pos
